package browser

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"sort"

	"gitee.com/baixudong/gospider/tools"
	"github.com/xujiajun/nutsdb"
)

type dbClient struct {
	db   *nutsdb.DB
	name string
}

func (obj *dbClient) close() error {
	return obj.db.Close()
}
func (obj *dbClient) keyMd5(key RequestOption, proxy string) []byte {
	var md5Str string
	md5Str += fmt.Sprintf("%s,%s,%s,%s", key.Method, key.Url, key.PostData, proxy)
	kks := []string{}
	for k := range key.Headers {
		kks = append(kks, k)
	}
	sort.Strings(kks)
	for _, k := range kks {
		md5Str += fmt.Sprintf("%s,%s", k, key.Headers[k])
	}
	return tools.StringToBytes(tools.Hex(tools.Md5(md5Str)))
}
func (obj *dbClient) put(key RequestOption, proxy string, val any, ttl uint32) error {
	return obj.db.Update(
		func(tx *nutsdb.Tx) error {
			valNetwork := bytes.NewBuffer(nil)
			if err := gob.NewEncoder(valNetwork).Encode(val); err != nil {
				return err
			}
			if err := tx.Put(obj.name, obj.keyMd5(key, proxy), valNetwork.Bytes(), ttl); err != nil {
				return err
			}
			return nil
		})
}
func (obj *dbClient) get(key RequestOption, val any, proxy string) error {
	return obj.db.View(
		func(tx *nutsdb.Tx) error {
			e, err := tx.Get(obj.name, obj.keyMd5(key, proxy))
			if err != nil || e == nil {
				return err
			}
			return gob.NewDecoder(bytes.NewReader(e.Value)).Decode(val)
		})
}
func newDbClient(dir string) (*dbClient, error) {
	option := nutsdb.DefaultOptions
	option.EntryIdxMode = nutsdb.HintKeyAndRAMIdxMode
	db, err := nutsdb.Open(
		option,
		nutsdb.WithDir(dir),
	)
	return &dbClient{db: db, name: "goSpider"}, err
}
